﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.IO;
using Com.CodePlex.SPC3.SPbAM.Data;
using Com.CodePlex.SPC3.SPbAM.Controller;
using Com.CodePlex.SPC3.SPbAM.Model;
using System.Windows.Input;
//using Com.CodePlex.SPC3.SPbAM.View; //should not reference this http://social.msdn.microsoft.com/Forums/is/wpf/thread/3bced3ea-4a97-4456-bfe5-828289bcf971

namespace Com.CodePlex.SPC3.SPbAM.ViewModel {

	//http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx

	public class ServerWorkspaceViewModel : ViewModel {

		#region Class
		private static readonly ServerWorkspaceRepository serverworkspacerepository = new ServerWorkspaceRepository(); //todo: IoC
		private static int newcount = 1;

		public static ServerWorkspaceViewModel GetNew() {
			ServerWorkspace serverworkspace = new ServerWorkspace() { Filename = @"c:\new" + (newcount++) + ".xml" };
			ServerWorkspaceViewModel model = new ServerWorkspaceViewModel(serverworkspace);
			model.IsModified = true;
			return model;
		}

		public static ServerWorkspaceViewModel GetOpening(string filename) {
			ServerWorkspace serverworkspace = new ServerWorkspace() { Filename = filename };
			ServerWorkspaceViewModel model = new ServerWorkspaceViewModel(serverworkspace);
			model.children = new ObservableCollection<ViewModel>();
            model.Children.Add(new ServerGroupViewModel(new ServerGroup() { Name = "Loading Workspace..." }, model));
			return model;
		}
		#endregion

		private readonly ServerWorkspace serverworkspace;

		public ServerWorkspaceViewModel(ServerWorkspace serverworkspace) {
			if (serverworkspace == null) {
				throw new ArgumentNullException("serverworkspace");
			}
			this.serverworkspace = serverworkspace;
			DisplayName = new FileInfo(serverworkspace.Filename).Name;
			Mediator.Register(this);
			//note: lazy load: dont do more stuff here
            AppendLog("Log started");
		}

		#region Commands

		private ICommand savecommand;
		public ICommand SaveCommand { get { return savecommand ?? (savecommand = new RelayCommand(param => Save())); } }

		private ICommand newservergroupcommand;
		public ICommand NewServerGroupCommand { get { return newservergroupcommand ?? (newservergroupcommand = new RelayCommand(param => NewServerGroup())); } }

		private ICommand newservercommand;
		public ICommand NewServerCommand { get { return newservercommand ?? (newservercommand = new RelayCommand(param => NewServer())); } }

		private ObservableCollection<CommandViewModel> treecommands;
		public ObservableCollection<CommandViewModel> TreeCommands {
			get {
				if (treecommands == null) {
					treecommands = new ObservableCollection<CommandViewModel>() {
						new CommandViewModel("New Server Group", NewServerGroupCommand),
						new CommandViewModel("New Server", NewServerCommand)
					};
				}
				return treecommands;
			}
		}

		#endregion

		#region Display Properties

		private bool ismodified;
		public bool IsModified {
			get { return ismodified; }
			set {
				if (ismodified != value) {
					ismodified = value;
					OnPropertyChanged(() => IsModified);
				}
			}
		}

        private DateTime datecreated = DateTime.Now;
        public DateTime DateCreated {
            get { return datecreated; }
        }

        private string log = "";
        public string Log {
            get { return log; }
            set {
                if (value != log) {
                    log = value;
                    OnPropertyChanged(() => Log);
                }
            }
        }
        public void AppendLog(string message) {
            Log += DateTime.Now + ": " + message + "\n";
        }

		private ObservableCollection<ViewModel> children;
		public ObservableCollection<ViewModel> Children {
			get {
				if (children == null) {
					children = new ObservableCollection<ViewModel>();
					children.CollectionChanged += children_CollectionChanged;
				}
				return children;
			}
		}

		private void children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) {
			/*
			if (e.NewItems != null && e.NewItems.Count != 0) {
				foreach (ViewModel model in e.NewItems) {
					if (model is ServerGroupViewModel) {
						//((ServerGroupViewModel)model).
						//serverworkspace.Children.Add(new ServerGroup() { Name = "New" });
					}
					//custVM.PropertyChanged += this.OnCustomerViewModelPropertyChanged;
				}
			}
			if (e.OldItems != null && e.OldItems.Count != 0) {
				foreach (ViewModel model in e.OldItems) {
					//custVM.PropertyChanged -= this.OnCustomerViewModelPropertyChanged;
				}
			}
			 * */
		}

		#endregion

		public void Load(Action<int> ReportProgress) {
			serverworkspacerepository.Load(serverworkspace, ReportProgress);
		}

		public void DataBind() {
			Children.Clear();
			(
				from child in serverworkspace.Children
				where child is ServerGroup
				select (ViewModel)(new ServerGroupViewModel((ServerGroup)child, this))
			).Union(
				from child in serverworkspace.Children
				where child is Server
                select (ViewModel)(new ServerViewModel((Server)child, this))
			).ToList<ViewModel>().ForEach(
				i => {
					if(i is ServerGroupViewModel) {
						((ServerGroupViewModel)i).DataBind();
					}
					Children.Add(i);
				}
			);
		}

		private void NewServerGroup() {
			ServerGroup servergroup = new ServerGroup() { Name = "New" };
			serverworkspace.Children.Add(servergroup);
            ServerGroupViewModel model = new ServerGroupViewModel(servergroup, this);
			Children.Add(model);
		}

		private void NewServer() {
			Server server = new Server() { Name = "New" };
			serverworkspace.Children.Add(server);
            ServerViewModel model = new ServerViewModel(server, this);
			Children.Add(model);
		}

		private void Save() {
			//serverworkspacerepository.Save(serverworkspace, serverworkspace.Filename, (i) => {
				//saveworker.ReportProgress(i);
			//});
		}

		[MediatorMessageSink(SimpleMessage.Exit, ParameterType = typeof(SimpleMessage))]
		public void Exit(SimpleMessage message) {
			int i = 0;
		}

		protected override void OnDispose() {
			foreach (ViewModel viewmodel in Children) {
				viewmodel.Dispose();
			}
			this.Children.Clear();
			this.Children.CollectionChanged -= children_CollectionChanged;
		}
	}
}